Skip to content

fix(models-dev): prevent OOM crash on first launch#26781

Merged
raycastbot merged 3 commits intoraycast:mainfrom
carlesandres:ext/models-dev
Mar 31, 2026
Merged

fix(models-dev): prevent OOM crash on first launch#26781
raycastbot merged 3 commits intoraycast:mainfrom
carlesandres:ext/models-dev

Conversation

@carlesandres
Copy link
Copy Markdown
Contributor

@carlesandres carlesandres commented Mar 30, 2026

Summary

Fixes JS heap out of memory crash that occurs when opening the extension for the first time (empty cache).

Problem

useCachedPromise uses ~4x more memory than direct fetch when populating an empty cache. For our dataset (~1.6 MB JSON, ~4,100 models), this caused the worker to exceed its memory limit and crash before rendering.

This only affected first-time users or users who cleared their cache—subsequent launches worked fine.

Solution

Replaced useCachedPromise with direct fetch + Raycast's Cache API. This:

  • Reduces peak memory from ~82 MB to ~22 MB during initial load
  • Maintains the same stale-while-revalidate behavior
  • Removes the @raycast/utils dependency (no longer needed)

Related issue filed: raycast/utils#67

Checklist

- chore: ignore local debug files
- fix: replace useCachedPromise with direct fetch to prevent OOM on first launch
- Pull contributions
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: models-dev Issues related to the models-dev extension platform: macOS OP is author The OP of the PR is the author of the extension labels Mar 30, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Thank you for the update! 🎉

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

@carlesandres carlesandres changed the title Update models-dev extension fix(models-dev): prevent OOM crash on first launch Mar 30, 2026
@carlesandres carlesandres marked this pull request as ready for review March 30, 2026 20:21
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 30, 2026

Greptile Summary

This PR fixes a JS heap out-of-memory crash on first launch by replacing useCachedPromise (from @raycast/utils) with a hand-rolled stale-while-revalidate pattern using React's useState/useEffect and Raycast's built-in Cache API. The change reduces peak memory during initial data load from ~82 MB to ~22 MB, addressing a real crash for first-time users.

Key changes:

  • useModelsData.ts: New implementation reads from Cache synchronously on mount, renders immediately with stale data, then fetches fresh data in the background — mirroring the original keepPreviousData behavior with far lower memory overhead.
  • package.json / package-lock.json: @raycast/utils and its dequal transitive dependency removed.
  • CHANGELOG.md: New entry added at the top with correct {PR_MERGE_DATE} placeholder.
  • .gitignore: Local development artifacts (.claude/, GITHUB_ISSUE.md) excluded from version control.

The implementation is logically sound. Two minor style nits: a placeholder issues/XXX URL in a comment should be updated to the real issue number (65), and a setIsLoading(true) call inside the effect is redundant since isLoading is already initialized to true in that code path.

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style nits with no impact on correctness or behavior.

The core logic is correct: the stale-while-revalidate semantics are preserved, error handling is appropriate, the fetchedRef guard correctly prevents double-fetching in React StrictMode, and the cache write is deliberately deferred after state update to minimize peak heap. Only two minor style issues remain (a stale placeholder URL and a redundant state setter), neither of which affects runtime behavior.

No files require special attention.

Important Files Changed

Filename Overview
extensions/models-dev/src/hooks/useModelsData.ts Replaces useCachedPromise with manual useState/useEffect + Raycast Cache API to fix OOM crash; logic is sound with two minor style nits (placeholder URL, redundant state setter).
extensions/models-dev/package.json Removes @raycast/utils dependency since it is no longer needed after replacing useCachedPromise.
extensions/models-dev/CHANGELOG.md New entry added at the top with correct {PR_MERGE_DATE} placeholder and descending version order.
extensions/models-dev/.gitignore Adds .claude/ and GITHUB_ISSUE.md to prevent local development artifacts from being committed.
extensions/models-dev/package-lock.json Lockfile updated to remove @raycast/utils and its dequal transitive dependency.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/models-dev/src/hooks/useModelsData.ts
Line: 13-14

Comment:
**Placeholder issue URL not updated**

The comment references `issues/XXX` which is a placeholder. Based on the PR description, the actual filed issue is `https://github.com/raycast/utils/issues/65`. This should be updated to point to the real issue for future maintainers.

```suggestion
 * Uses direct fetch + Cache API instead of useCachedPromise to avoid
 * memory spikes during fresh cache population. See:
 * https://github.com/raycast/utils/issues/65
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/models-dev/src/hooks/useModelsData.ts
Line: 29-42

Comment:
**Redundant `setIsLoading(true)` call**

`isLoading` is already initialized to `!data` on line 29, so when `shouldRevalidate` is `false` (i.e. `data` is `null`), `isLoading` is already `true`. The `setIsLoading(true)` call inside the `if (!shouldRevalidate)` block is a no-op on first render and triggers an unnecessary re-render in React StrictMode (where the effect body runs twice).

```suggestion
  const [isLoading, setIsLoading] = useState(!data);
  const fetchedRef = useRef(false);

  useEffect(() => {
    // Already have cached data or already fetching
    if (fetchedRef.current) return;
    fetchedRef.current = true;

    // If we have cached data, still revalidate in background
    const shouldRevalidate = !!data;
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Update models-dev extension" | Re-trigger Greptile

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@carlesandres
Copy link
Copy Markdown
Contributor Author

@0xdhrv @pernielsentikaer This one should be relatively straightforward.

@pernielsentikaer pernielsentikaer self-assigned this Mar 31, 2026
Copy link
Copy Markdown
Collaborator

@pernielsentikaer pernielsentikaer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, approved 🔥

@raycastbot raycastbot merged commit 896bed9 into raycast:main Mar 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Published to the Raycast Store:
https://raycast.com/carlesandres/models-dev

@raycastbot
Copy link
Copy Markdown
Collaborator

🎉 🎉 🎉

We've rewarded your Raycast account with some credits. You will soon be able to exchange them for some swag.

@carlesandres carlesandres deleted the ext/models-dev branch April 9, 2026 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension fix / improvement Label for PRs with extension's fix improvements extension: models-dev Issues related to the models-dev extension OP is author The OP of the PR is the author of the extension platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants